import { httpClient, HttpClient, ApiResponse } from '@/utils/http-client'
import { ElMessage, ElLoading } from 'element-plus'
import { Ref, ref } from 'vue'

/**
 * 分页请求参数接口
 */
export interface PaginationParams {
  skipCount?: number
  maxResultCount?: number
  sorting?: string
  filter?: string
}

/**
 * 分页响应接口
 */
export interface PagedResponse<T> {
  items: T[]
  totalCount: number
}

/**
 * 批量操作参数接口
 */
export interface BatchOperationParams {
  ids: string[]
  action: string
  parameters?: Record<string, any>
}

/**
 * 批量操作结果接口
 */
export interface BatchOperationResult {
  successCount: number
  failureCount: number
  results: Array<{
    id: string
    success: boolean
    error?: string
  }>
}

/**
 * 导入导出参数接口
 */
export interface ImportExportParams {
  file?: File
  format?: 'json' | 'excel' | 'csv'
  filters?: Record<string, any>
  columns?: string[]
}

/**
 * API服务基类
 * 提供通用的CRUD操作和工具方法
 */
export abstract class BaseApiService {
  protected http: HttpClient
  protected loading: Ref<boolean>
  protected loadingInstance: any = null

  constructor(httpClient?: HttpClient) {
    this.http = httpClient || httpClient
    this.loading = ref(false)
  }

  /**
   * 显示加载状态
   */
  protected showLoading(message = '加载中...'): void {
    this.loading.value = true
    this.loadingInstance = ElLoading.service({
      lock: true,
      text: message,
      background: 'rgba(0, 0, 0, 0.7)'
    })
  }

  /**
   * 隐藏加载状态
   */
  protected hideLoading(): void {
    this.loading.value = false
    if (this.loadingInstance) {
      this.loadingInstance.close()
      this.loadingInstance = null
    }
  }

  /**
   * 处理API响应
   */
  protected async handleRequest<T>(
    requestFn: () => Promise<ApiResponse<T>>,
    options: {
      showLoading?: boolean
      loadingMessage?: string
      showSuccessMessage?: boolean
      successMessage?: string
      showError?: boolean
      transformData?: (data: T) => any
    } = {}
  ): Promise<T> {
    const {
      showLoading: shouldShowLoading = true,
      loadingMessage = '处理中...',
      showSuccessMessage = false,
      successMessage = '操作成功',
      showError = true,
      transformData
    } = options

    try {
      if (shouldShowLoading) {
        this.showLoading(loadingMessage)
      }

      const response = await requestFn()

      if (!response.success) {
        const error = response.error
        const errorMessage = error?.message || '操作失败'

        if (showError) {
          ElMessage.error(errorMessage)
        }

        throw new Error(errorMessage)
      }

      const data = response.data as T

      if (showSuccessMessage && successMessage) {
        ElMessage.success(successMessage)
      }

      return transformData ? transformData(data) : data
    } catch (error) {
      console.error('API请求失败:', error)

      if (showError && !(error as Error).message.includes('ElMessage')) {
        ElMessage.error((error as Error).message || '操作失败')
      }

      throw error
    } finally {
      if (shouldShowLoading) {
        this.hideLoading()
      }
    }
  }

  /**
   * 通用分页查询
   */
  protected async getPaged<T>(
    url: string,
    params: PaginationParams = {},
    options: {
      showLoading?: boolean
      transformData?: (data: T) => any
    } = {}
  ): Promise<PagedResponse<T>> {
    const defaultParams: PaginationParams = {
      skipCount: 0,
      maxResultCount: 20,
      ...params
    }

    return this.handleRequest(
      () => this.http.get<PagedResponse<T>>(url, defaultParams),
      options
    )
  }

  /**
   * 通用详情查询
   */
  protected async getById<T>(
    url: string,
    id: string,
    options: {
      showLoading?: boolean
      transformData?: (data: T) => any
    } = {}
  ): Promise<T> {
    return this.handleRequest(
      () => this.http.get<T>(`${url}/${id}`),
      options
    )
  }

  /**
   * 通用创建
   */
  protected async create<T>(
    url: string,
    data: any,
    options: {
      showLoading?: boolean
      showSuccessMessage?: boolean
      successMessage?: string
      transformData?: (data: T) => any
    } = {}
  ): Promise<T> {
    return this.handleRequest(
      () => this.http.post<T>(url, data),
      {
        showSuccessMessage: true,
        successMessage: '创建成功',
        ...options
      }
    )
  }

  /**
   * 通用更新
   */
  protected async update<T>(
    url: string,
    id: string,
    data: any,
    options: {
      showLoading?: boolean
      showSuccessMessage?: boolean
      successMessage?: string
      transformData?: (data: T) => any
    } = {}
  ): Promise<T> {
    return this.handleRequest(
      () => this.http.put<T>(`${url}/${id}`, data),
      {
        showSuccessMessage: true,
        successMessage: '更新成功',
        ...options
      }
    )
  }

  /**
   * 通用删除
   */
  protected async delete(
    url: string,
    id: string,
    options: {
      showLoading?: boolean
      showSuccessMessage?: boolean
      successMessage?: string
      confirmMessage?: string
    } = {}
  ): Promise<void> {
    const {
      showLoading = true,
      showSuccessMessage = true,
      successMessage = '删除成功',
      confirmMessage = '确定要删除此项吗？此操作不可撤销。'
    } = options

    // 显示确认对话框
    if (confirmMessage) {
      try {
        await ElMessageBox.confirm(confirmMessage, '确认删除', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      } catch {
        // 用户取消操作
        return Promise.resolve()
      }
    }

    return this.handleRequest(
      () => this.http.delete(`${url}/${id}`),
      {
        showLoading,
        showSuccessMessage,
        successMessage
      }
    )
  }

  /**
   * 批量删除
   */
  protected async batchDelete(
    url: string,
    ids: string[],
    options: {
      showLoading?: boolean
      showSuccessMessage?: boolean
      successMessage?: string
      confirmMessage?: string
    } = {}
  ): Promise<BatchOperationResult> {
    const {
      showLoading = true,
      showSuccessMessage = true,
      successMessage = '批量删除完成',
      confirmMessage = `确定要删除选中的 ${ids.length} 项吗？此操作不可撤销。`
    } = options

    // 显示确认对话框
    if (confirmMessage && ids.length > 0) {
      try {
        await ElMessageBox.confirm(confirmMessage, '确认删除', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      } catch {
        // 用户取消操作
        return Promise.resolve({
          successCount: 0,
          failureCount: 0,
          results: []
        })
      }
    }

    return this.handleRequest(
      () => this.http.post<BatchOperationResult>(`${url}/batch-delete`, { ids }),
      {
        showLoading,
        showSuccessMessage,
        successMessage
      }
    )
  }

  /**
   * 批量操作
   */
  protected async batchOperation(
    url: string,
    params: BatchOperationParams,
    options: {
      showLoading?: boolean
      showSuccessMessage?: boolean
      successMessage?: string
    } = {}
  ): Promise<BatchOperationResult> {
    return this.handleRequest(
      () => this.http.post<BatchOperationResult>(`${url}/batch-operation`, params),
      {
        showSuccessMessage: true,
        successMessage: '批量操作完成',
        ...options
      }
    )
  }

  /**
   * 导出数据
   */
  protected async export(
    url: string,
    params: ImportExportParams = {},
    options: {
      showLoading?: boolean
      loadingMessage?: string
      filename?: string
    } = {}
  ): Promise<void> {
    const {
      showLoading = true,
      loadingMessage = '导出中...',
      filename = `export_${Date.now()}.${params.format || 'xlsx'}`
    } = options

    try {
      if (showLoading) {
        this.showLoading(loadingMessage)
      }

      await this.http.download(url, filename, {
        params,
        responseType: 'blob'
      })

      ElMessage.success('导出成功')
    } catch (error) {
      console.error('导出失败:', error)
      ElMessage.error('导出失败')
      throw error
    } finally {
      if (showLoading) {
        this.hideLoading()
      }
    }
  }

  /**
   * 导入数据
   */
  protected async import<T>(
    url: string,
    params: ImportExportParams,
    options: {
      showLoading?: boolean
      loadingMessage?: string
      showSuccessMessage?: boolean
      successMessage?: string
      transformData?: (data: T) => any
    } = {}
  ): Promise<T> {
    const {
      showLoading = true,
      loadingMessage = '导入中...',
      showSuccessMessage = true,
      successMessage = '导入成功'
    } = options

    if (!params.file) {
      ElMessage.error('请选择要导入的文件')
      return Promise.reject(new Error('未选择文件'))
    }

    const formData = new FormData()
    formData.append('file', params.file)

    if (params.format) {
      formData.append('format', params.format)
    }

    if (params.filters) {
      formData.append('filters', JSON.stringify(params.filters))
    }

    if (params.columns) {
      formData.append('columns', JSON.stringify(params.columns))
    }

    return this.handleRequest(
      () => this.http.upload<T>(url, formData),
      {
        showLoading,
        loadingMessage,
        showSuccessMessage,
        successMessage,
        ...options
      }
    )
  }

  /**
   * 获取导入模板
   */
  protected async getImportTemplate(
    url: string,
    format: string = 'xlsx',
    options: {
      filename?: string
    } = {}
  ): Promise<void> {
    const { filename = `import_template.${format}` } = options

    try {
      await this.http.download(`${url}/template?format=${format}`, filename)
      ElMessage.success('模板下载成功')
    } catch (error) {
      console.error('模板下载失败:', error)
      ElMessage.error('模板下载失败')
      throw error
    }
  }

  /**
   * 搜索建议
   */
  protected async searchSuggestions<T>(
    url: string,
    keyword: string,
    options: {
      limit?: number
      showLoading?: boolean
    } = {}
  ): Promise<T[]> {
    const { limit = 10, showLoading = false } = options

    return this.handleRequest(
      () => this.http.get<T[]>(url, { keyword, limit }),
      { showLoading }
    )
  }

  /**
   * 验证数据
   */
  protected async validate<T>(
    url: string,
    data: any,
    options: {
      showLoading?: boolean
    } = {}
  ): Promise<{
    isValid: boolean
    errors?: Array<{
      field: string
      message: string
    }>
  }> {
    return this.handleRequest(
      () => this.http.post<{
        isValid: boolean
        errors?: Array<{
          field: string
          message: string
        }>
      }>(`${url}/validate`, data),
      { showLoading: false, ...options }
    )
  }

  /**
   * 获取统计信息
   */
  protected async getStatistics<T>(
    url: string,
    params: Record<string, any> = {},
    options: {
      showLoading?: boolean
    } = {}
  ): Promise<T> {
    return this.handleRequest(
      () => this.http.get<T>(url, params),
      { showLoading: false, ...options }
    )
  }

  /**
   * 获取当前加载状态
   */
  get isLoading(): boolean {
    return this.loading.value
  }
}

/**
 * 创建API服务实例
 */
export function createApiService<T extends BaseApiService>(
  ServiceClass: new (httpClient?: HttpClient) => T,
  httpClient?: HttpClient
): T {
  return new ServiceClass(httpClient)
}

/**
 * API响应处理工具
 */
export class ApiResponseHandler {
  /**
   * 处理成功响应
   */
  static handleSuccess<T>(
    response: ApiResponse<T>,
    options: {
      showMessage?: boolean
      message?: string
    } = {}
  ): T {
    const { showMessage = false, message } = options

    if (!response.success) {
      throw new Error(response.error?.message || '操作失败')
    }

    if (showMessage && message) {
      ElMessage.success(message)
    }

    return response.data as T
  }

  /**
   * 处理错误响应
   */
  static handleError(error: any, options: {
    showMessage?: boolean
    defaultMessage?: string
  } = {}): never {
    const { showMessage = true, defaultMessage = '操作失败' } = options

    console.error('API错误:', error)

    if (showMessage) {
      const message = error?.message || error?.response?.data?.error?.message || defaultMessage
      ElMessage.error(message)
    }

    throw error
  }

  /**
   * 安全地执行API操作
   */
  static async safeExecute<T>(
    operation: () => Promise<ApiResponse<T>>,
    options: {
      showSuccessMessage?: boolean
      successMessage?: string
      showErrorMessage?: boolean
      errorMessage?: string
    } = {}
  ): Promise<T | null> {
    try {
      const response = await operation()
      return this.handleSuccess(response, options)
    } catch (error) {
      this.handleError(error, {
        showMessage: options.showErrorMessage,
        defaultMessage: options.errorMessage
      })
      return null
    }
  }
}